package com.bicon.botu.mall.order.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bicon.botu.core.base.common.BusinessException;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.utils.JsonUtil;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.mall.order.common.OrderConstans;
import com.bicon.botu.mall.order.common.OrderUtil;
import com.bicon.botu.mall.order.dto.*;
import com.bicon.botu.mall.order.entity.*;
import com.bicon.botu.mall.order.mapper.OrderDeliverMapper;
import com.bicon.botu.mall.order.service.*;
import com.bicon.botu.mall.order.thirdparty.kdniao.KdniaoApi;
import com.bicon.botu.mall.order.thirdparty.kdniao.dto.TrackResult;
import com.bicon.botu.third.provider.rpc.service.MessageRpcService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 发货
 *
 * @author 李双喜
 * @date 2018/5/14 12:57
 */
@Service
@Slf4j
public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, OrderDeliver> implements IOrderDeliverService {

    @Autowired
    OrderDeliverMapper orderDeliverMapper;

    @Autowired
    KdniaoApi kdniaoApi;

    @Autowired
    private IMyInvoiceService iMyInvoiceService;

    @Autowired
    private IOrderGoodsService iOrderGoodsService;

    @Autowired
    private IOrderDetailAddressService iOrderDetailAddressService;
    @Autowired
    private RedisHandler redisHandler;

    @Autowired
    private IOrderDetailService iOrderDetailService;

    @Autowired
    private IOrderChildService iOrderChildService;

    @Autowired
    private IOrderReceiptService iOrderReceiptService;

    @Autowired
    private MessageRpcService messageRpcService;

    @Value("${mall.order.templateCode}")
    private String templateCode;

    @Value("${mall.order.signName}")
    private String signName;



    @Override
    public OrderLogisticsDto getLogistics(String orderId) {
        OrderLogistics orderLogistics = this.orderDeliverMapper.queryOrderLogistics(orderId);
        if (orderLogistics == null) {
            throw new BusinessException(Constants.RESPONSE_CODE_500, "订单物流信息查询失败");
        }
        TrackResult trackResult = null;
        try {
            trackResult = this.kdniaoApi.getOrderTracesByJson(orderLogistics.getLogisticsCompanyCode(), orderLogistics.getLogisticsCode());
        } catch (Exception e) {
            throw new BusinessException(Constants.RESPONSE_CODE_500, "调用第三方API查询物流信息失败");
        }
        OrderLogisticsDto result = new OrderLogisticsDto();
        result.setLogisticsCompanyName(orderLogistics.getLogisticsCompanyName());
        result.setLogisticsCompanyPhone(orderLogistics.getLogisticsCompanyPhone());
        result.setLogisticsCompanyWebsite(orderLogistics.getLogisticsCompanyWebsite());
        result.setLogisticsCode(orderLogistics.getLogisticsCode());
        Collections.reverse(trackResult.getTraces());
        result.setTraces(trackResult.getTraces());


        for (int i = 0; i < result.getTraces().size(); i++) {
            result.getTraces().get(i).setAcceptTime(result.getTraces().get(i).getAcceptTime().replaceAll("/", "-"));
        }

        return result;
    }


    /**
     * 发货单
     *
     * @param storeId       商铺id
     * @param orderGoodsIds 多个分组订单id
     * @param userId        操作人的用户id
     * @return
     */
    @Override
    public List<DeliveryDto> printDeliver(String storeId, String orderGoodsIds, String userId) {
        String[] orderGoodsIdArray = orderGoodsIds.split(",");
        String userName = this.checkName(userId);

        List<OrderGoods> orderGoodsList = iOrderGoodsService.selectList(new EntityWrapper<OrderGoods>().in("id", orderGoodsIdArray).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        List<DeliveryDto> deliveryDtos = new ArrayList();
        //获取所有的发票信息
        String[] myInvoiceIds = orderGoodsList.stream().distinct().map(OrderGoods::getInvoiceId).toArray(String[]::new);
        List<MyInvoice> myInvoiceList = iMyInvoiceService.selectList(new EntityWrapper<MyInvoice>()
                .in("id", myInvoiceIds).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, MyInvoice> myInvoiceMap = new HashMap<>(32);
        for (MyInvoice myInvoice : myInvoiceList) {
            myInvoiceMap.put(myInvoice.getId(), myInvoice);
        }
        //查询分组订单对应的商品
        List<OrderDetail> orderDetailList = iOrderDetailService.selectList(new EntityWrapper<OrderDetail>()
                .in("main_order_id", orderGoodsIdArray).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, List<GoodsDto>> map = new HashMap<>(32);

        setGoodsDtoMethod(orderDetailList, map);

        //查询对应的地址信息
        List<OrderDetailAddress> orderDetailAddressList = iOrderDetailAddressService.selectList(new EntityWrapper<OrderDetailAddress>()
                .in("main_order_id", orderGoodsIdArray).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, OrderDetailAddress> mapAddress = new HashMap<>(32);
        for (OrderDetailAddress orderDetailAddress : orderDetailAddressList) {
            mapAddress.put(orderDetailAddress.getOrderGoodsId(), orderDetailAddress);
        }
        //查询各个价格
        List<OrderChild> orderChildList = iOrderChildService.selectList(new EntityWrapper<OrderChild>()
                .in("main_order_id", orderGoodsIdArray).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, List<OrderChild>> orderChildMap = new HashMap<>(32);
        for (OrderChild orderChild : orderChildList) {
            if (orderChildMap.containsKey(orderChild.getMainOrderId())) {
                orderChildMap.get(orderChild.getMainOrderId()).add(orderChild);
            } else {
                List<OrderChild> childList = new ArrayList<>();
                childList.add(orderChild);
                orderChildMap.put(orderChild.getMainOrderId(), childList);
            }
        }
        Map<String, BigDecimal> orderReceiptMap = getStringBigDecimalMap(orderGoodsList);
        //查询出发票信息
        deliverDtoMethod(userName, orderGoodsList, deliveryDtos, myInvoiceMap, map, mapAddress, orderChildMap, orderReceiptMap);
        return deliveryDtos;
    }

    /**
     * 设置deliveryDto值
     *
     * @param userName
     * @param orderGoodsList
     * @param deliveryDtos
     * @param myInvoiceMap
     * @param map
     * @param mapAddress
     * @param orderChildMap
     * @param orderReceiptMap
     */
    private void deliverDtoMethod(String userName, List<OrderGoods> orderGoodsList, List<DeliveryDto> deliveryDtos, Map<String, MyInvoice> myInvoiceMap, Map<String, List<GoodsDto>> map, Map<String, OrderDetailAddress> mapAddress, Map<String, List<OrderChild>> orderChildMap, Map<String, BigDecimal> orderReceiptMap) {
        for (OrderGoods orderGoods : orderGoodsList) {
            DeliveryDto deliveryDto = new DeliveryDto();
            if (StringUtils.isNotEmpty(orderGoods.getInvoiceId())) {
                MyInvoice myInvoice = myInvoiceMap.get(orderGoods.getInvoiceId());
                if (null != myInvoice) {
                    MyInvoiceOrderDto myInvoiceOrderDto = new MyInvoiceOrderDto();
                    myInvoiceOrderDto.setContent(myInvoice.getContent());
                    myInvoiceOrderDto.setHead(myInvoice.getHead());
                    myInvoiceOrderDto.setType(myInvoice.getType());
                    if (myInvoice.getHead() == 1) {
                        myInvoiceOrderDto.setCompanyName(myInvoice.getCompanyName());
                        myInvoiceOrderDto.setRateNumber(myInvoice.getRateNumber());
                        myInvoiceOrderDto.setCheckTakerPhone(myInvoice.getCheckTakerPhone());
                        myInvoiceOrderDto.setCheckTakerMail(myInvoice.getCheckTakerMail());
                    }
                    deliveryDto.setMyInvoiceOrderDto(myInvoiceOrderDto);
                }
            }
            deliveryDto.setCreateTime(orderGoods.getCreateDate());
            deliveryDto.setOrderNo(orderGoods.getOrderGoodsNo());
            deliveryDto.setGoodsDtoList(map.get(orderGoods.getId()));
            deliveryDto.setOperator(userName);
            deliveryDto.setTotalFreight(orderGoods.getFreight());
            deliveryDto.setPrintDate(new Date());
            OrderDetailAddress orderDetailAddress = mapAddress.get(orderGoods.getId());
            BeanUtils.copyProperties(orderDetailAddress, deliveryDto);
            deliveryDto.setRemark(orderGoods.getBuyerMessage());
            deliveryDto.setPayWay(orderGoods.getPayWay());
            deliveryDto.setPayTime(orderGoods.getPayTime());
            deliveryDto.setTotalPayment(orderReceiptMap.get(orderGoods.getOrderReceiptId()));
            List<OrderChild> orderChildren = orderChildMap.get(orderGoods.getId());
            //list中多个对象的某一个属性求和
            BigDecimal totalMoney = orderChildren.stream().map(OrderChild::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            deliveryDto.setTotalPrice(totalMoney);
            BigDecimal discountMoney = orderChildren.stream().map(OrderChild::getDiscountMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            deliveryDto.setTotalDiscount(discountMoney);
            deliveryDto.setTotalOrderPrice(totalMoney.subtract(discountMoney).add(orderGoods.getFreight()));
            deliveryDtos.add(deliveryDto);
        }
    }

    /**
     * 设置Goods详情值
     *
     * @param orderDetailList
     * @param map
     */
    private void setGoodsDtoMethod(List<OrderDetail> orderDetailList, Map<String, List<GoodsDto>> map) {
        for (OrderDetail orderDetail : orderDetailList) {
            if (map.containsKey(orderDetail.getMainOrderId())) {
                GoodsDto goodsDto = new GoodsDto();
                goodsDto.setGoodsName(orderDetail.getGoodsName());
                goodsDto.setSkuName(orderDetail.getSkuName());
                goodsDto.setPrice(orderDetail.getGoodsPlatformPrice());
                goodsDto.setProductCode(orderDetail.getProductCode());
                goodsDto.setUnit("件");
                goodsDto.setGoodsNumber(orderDetail.getGoodsNumber());
                goodsDto.setSubtotal(new BigDecimal(orderDetail.getGoodsNumber()).multiply(orderDetail.getGoodsPlatformPrice()));
                map.get(orderDetail.getMainOrderId()).add(goodsDto);
            } else {
                List<GoodsDto> goodsList = new ArrayList<>();
                GoodsDto goodsDto = new GoodsDto();
                goodsDto.setGoodsName(orderDetail.getGoodsName());
                goodsDto.setSkuName(orderDetail.getSkuName());
                goodsDto.setPrice(orderDetail.getGoodsPlatformPrice());
                goodsDto.setProductCode(orderDetail.getProductCode());
                goodsDto.setUnit("件");
                goodsDto.setGoodsNumber(orderDetail.getGoodsNumber());
                goodsDto.setSubtotal(new BigDecimal(orderDetail.getGoodsNumber()).multiply(orderDetail.getGoodsPlatformPrice()));
                goodsList.add(goodsDto);
                map.put(orderDetail.getMainOrderId(), goodsList);
            }
        }
    }

    private Map<String, BigDecimal> getStringBigDecimalMap(List<OrderGoods> orderGoodsList) {
        //查询支付金额
        String[] receiptIds = orderGoodsList.stream().map(OrderGoods::getOrderReceiptId).toArray(String[]::new);
        List<OrderReceipt> orderReceiptList = iOrderReceiptService.selectList(new EntityWrapper<OrderReceipt>()
                .in("id", receiptIds).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, BigDecimal> orderReceiptMap = new HashMap<>(32);
        for (OrderReceipt orderReceipt : orderReceiptList) {
            orderReceiptMap.put(orderReceipt.getId(), orderReceipt.getMoney());
        }
        return orderReceiptMap;
    }

    /**
     * 查询操作名称
     *
     * @param userId
     * @return
     */

    public String checkName(String userId) {

        String userInFo = redisHandler.getGlobalRedisTemplate().getStringValue(OrderConstans.LIFE_USER_USERINFO, userId);
        UserInfoVo userInfoDto = JSONArray.parseObject(userInFo, UserInfoVo.class);
        if (null != userInfoDto && null != userInfoDto.getName()) {
            return userInfoDto.getName();
        }
        return null;

    }

    /**
     * 查询用户手机号码
     *
     * @param userId
     * @return
     */
    public String checkPhone(String userId) {
        String userInFo = redisHandler.getGlobalRedisTemplate().getStringValue(OrderConstans.LIFE_USER_USERINFO, userId);
        UserInfoVo userInfoDto = JSONArray.parseObject(userInFo, UserInfoVo.class);
        if (null != userInfoDto && null != userInfoDto.getPhone()) {
            return userInfoDto.getPhone();
        }
        return null;

    }

    /**
     * 批量发货
     *
     * @param jsonString 多个分组订单id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeliver(String jsonString,String systemUserId) {
        Type type = new TypeReference<List<DeliverOrderDto>>() {
        }.getType();
        List<DeliverOrderDto> orderDtoList = JSONObject.parseObject(jsonString, type);
        List<String> orderGoodsIds = orderDtoList.stream().map(DeliverOrderDto::getOrderGoodsId).collect(Collectors.toList());
        List<OrderGoods> orderGoodsList = iOrderGoodsService.selectList(new EntityWrapper<OrderGoods>()
                .in("id", orderGoodsIds).eq("logic_delete", OrderConstans.DEL_LOGIC_NORMAL));
        List<MessageDto> messageDtoList = new ArrayList<>();
        for (OrderGoods orderGoods : orderGoodsList) {
            MessageDto messageDto = new MessageDto();
            messageDto.setOrderGoodsId(orderGoods.getId());
            messageDto.setOrderGoodsNo(orderGoods.getOrderGoodsNo());
            messageDto.setUserId(orderGoods.getUserId());
            String phone = this.checkPhone(orderGoods.getUserId());
            if (StringUtils.isEmpty(phone)) {
                continue;
            }
            messageDto.setPhone(phone);
            messageDtoList.add(messageDto);
        }
        List<OrderDeliver> deliverList = new ArrayList<>();
        List<OrderGoods> goodsList = new ArrayList<>();
        Map<String, DeliverOrderDto> map = new HashMap();
        orderDeliverListMethod(orderDtoList, orderGoodsList, deliverList, goodsList, map);
        boolean resultDeliver = this.insertBatch(deliverList);
        boolean resultOrderGoods = iOrderGoodsService.updateBatchById(goodsList);
        //拼装
        Map<String, String> mapMessage = new HashMap<>(32);
        List<Map> mapList = new ArrayList<>();
        List<String> listPhone = new ArrayList<>();
        for (MessageDto messageDto : messageDtoList) {
            DeliverOrderDto deliverOrderDto = map.get(messageDto.getOrderGoodsId());
            if (null != deliverOrderDto && StringUtils.isNotEmpty(messageDto.getPhone())) {
                messageDto.setWaybill(deliverOrderDto.getWaybill());
                mapMessage.put("orderNo", messageDto.getOrderGoodsNo());
                mapMessage.put("waybill", messageDto.getWaybill());
                listPhone.add(messageDto.getPhone());
                mapList.add(mapMessage);
            } else {
                continue;
            }
        }
        //订单记录
        String remark = null;
        if (orderGoodsList.size()>1) {
            remark = "批量发货";
        }else{
            remark = "订单已发货";
        }
        iOrderChildService.insertOrderRecord(systemUserId,orderGoodsList,remark);
        //发送短信
        messageRpcService.batchSendYunSms(JsonUtil.toJson(listPhone), JsonUtil.toJson(mapList), templateCode, signName);
        if (resultDeliver && resultOrderGoods) {
            return true;
        }
        return false;
    }

    /**
     * 增加DeliverOrderDto
     *
     * @param orderDtoList
     * @param orderGoodsList
     * @param deliverList
     * @param goodsList
     * @param map
     */
    private void orderDeliverListMethod(List<DeliverOrderDto> orderDtoList, List<OrderGoods> orderGoodsList, List<OrderDeliver> deliverList, List<OrderGoods> goodsList, Map<String, DeliverOrderDto> map) {
        for (DeliverOrderDto deliverOrderDto : orderDtoList) {
            OrderDeliver orderDeliver = new OrderDeliver();
            orderDeliver.preInsert();
            for (OrderGoods orderGoods : orderGoodsList) {
                if (orderGoods.getId().equals(deliverOrderDto.getOrderGoodsId())) {
                    orderGoods.setPayState(OrderConstans.ORDER_STATUS_3);
                    orderGoods.setLogisticsCompany(deliverOrderDto.getLogisticsCompany());
                    orderGoods.preUpdate();
                    orderGoods.setOrderDeliverId(orderDeliver.getId());
                    goodsList.add(orderGoods);
                }
            }
            map.put(deliverOrderDto.getOrderGoodsId(), deliverOrderDto);
            orderDeliver.setOrderAddressId(deliverOrderDto.getOrderAddressId());
            orderDeliver.setDeliverNo(OrderUtil.getOrderNo());
            orderDeliver.setWaybill(deliverOrderDto.getWaybill());
            orderDeliver.setOrderGoodsId(deliverOrderDto.getOrderGoodsId());
            orderDeliver.setLogisticsCompanyId(deliverOrderDto.getLogisticsCompanyId());
            orderDeliver.setUserId(deliverOrderDto.getUserId());
            orderDeliver.setStoreId(deliverOrderDto.getStoreId());
            orderDeliver.setStatus(1);
            deliverList.add(orderDeliver);
        }
    }

    /**
     * 订单确认完成
     *
     * @param orderGoodsId 分组订单id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderCompletion(String orderGoodsId,String systemUserId) {
        OrderGoods orderGoods = iOrderGoodsService.selectOne(new EntityWrapper<OrderGoods>()
                .eq("logic_delete", Constants.DEL_LOGIC_NORMAL).eq("id", orderGoodsId));
        orderGoods.setPayState(OrderConstans.ORDER_STATUS_4);
        orderGoods.setDealTime(new Date());
        orderGoods.preUpdate();
        if (StringUtils.isEmpty(orderGoods.getOrderDeliverId())) {
            throw new BusinessException("收货信息不存在");
        }
        OrderDeliver orderDeliver = this.selectOne(new EntityWrapper<OrderDeliver>().eq("logic_delete", Constants.DEL_LOGIC_NORMAL).eq("id", orderGoods.getOrderDeliverId()));
        orderDeliver.setStatus(2);
        orderDeliver.preUpdate();
        Boolean result = this.updateById(orderDeliver);

        //金融--平台转账给店铺（目前无店铺--RPC）--只需要加上店铺的余额

        Boolean resultOrder = orderGoods.updateById();
        if (result && resultOrder) {
            //订单记录
            List<OrderGoods> list = new ArrayList<>();
            list.add(orderGoods);
            String remark = "订单确认完成";
            iOrderChildService.insertOrderRecord(systemUserId,list,remark);
            return true;
        }
        return false;
    }

    /**
     * 发货信息
     *
     * @param orderGoodsId 分组订单id
     * @return
     */
    @Override
    public DeliverInformationDto deliverInformation(String orderGoodsId) {
        OrderGoods orderGoods = iOrderGoodsService.selectOne(new EntityWrapper<OrderGoods>()
                .eq("logic_delete", Constants.DEL_LOGIC_NORMAL).eq("id", orderGoodsId));
        if (null != orderGoods && null != orderGoods.getPayState()) {
            if (orderGoods.getPayState() == 1) {
                throw new BusinessException("该订单尚未支付");
            } else if (orderGoods.getPayState() == 2) {
                throw new BusinessException("该订单尚未发货");
            } else if (orderGoods.getPayState() == 5) {
                throw new BusinessException("该订单已关闭");
            } else if (orderGoods.getPayState() == 6) {
                throw new BusinessException("该订单已取消");
            } else if (orderGoods.getPayState() == 7) {
                throw new BusinessException("该订单交易中");
            }
        }
        OrderDeliver orderDeliver = this.selectOne(new EntityWrapper<OrderDeliver>()
                .eq("logic_delete", Constants.DEL_LOGIC_NORMAL).eq("id", orderGoods.getOrderDeliverId()));
        if (null == orderDeliver) {
            throw new BusinessException("该订单未发货");
        }
        OrderDetailAddress orderDetailAddress = iOrderDetailAddressService.selectOne(new EntityWrapper<OrderDetailAddress>().eq("logic_delete", Constants.DEL_LOGIC_NORMAL).eq("id", orderDeliver.getOrderAddressId()));
        DeliverInformationDto deliverInformationDto = new DeliverInformationDto();
        deliverInformationDto.setAddressDetail(orderDetailAddress.getProvince() + orderDetailAddress.getCity() + orderDetailAddress.getArea() + orderDetailAddress.getAddressDetail());
        deliverInformationDto.setCreateDate(orderGoods.getCreateDate());
        deliverInformationDto.setDeliverNo(orderDeliver.getDeliverNo());
        deliverInformationDto.setLogisticsCompany(orderGoods.getLogisticsCompany());
        deliverInformationDto.setName(orderDetailAddress.getName());
        deliverInformationDto.setWaybill(orderDeliver.getWaybill());
        deliverInformationDto.setTelephone(orderDetailAddress.getTelephone());
        return deliverInformationDto;
    }


}
